package com.yanqu.road.entity.activity.foxcard;

import com.yanqu.road.entity.DataObject;
import com.yanqu.road.entity.FieldTypeAnnotation;

import java.math.BigInteger;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

@FieldTypeAnnotation(tableName = "t_u_activity_fox_game", desc = "狐妖小红娘数据")
public class UserFoxCardGameData extends DataObject {
    @FieldTypeAnnotation(select = true, isIndex = true, update = true)
    private int activityId;
    @FieldTypeAnnotation(desc = "玩家id", select = true, isIndex = true, update = true)
    private long userId;
    @FieldTypeAnnotation(desc = "关卡id")
    private int stageId; //关卡id
    @FieldTypeAnnotation(desc = "回合数")
    private int round; //回合数
    @FieldTypeAnnotation(desc = "是否战斗中")
    private boolean inBattle;
    @FieldTypeAnnotation(desc = "效果牌上限")
    private int effectCardNumLimit; //效果牌上限
    @FieldTypeAnnotation(desc = "消耗牌上限")
    private int consumeCardNumLimit; //消耗牌上限
    @FieldTypeAnnotation(desc = "手牌上限")
    private int handCardNumLimit; //手牌上限
    @FieldTypeAnnotation(desc = "常驻效果牌")
    private List<FoxEffectCard> effectCards = new ArrayList<>(); //常驻效果牌
    @FieldTypeAnnotation(desc = "消耗牌")
    private List<FoxConsumeCard> consumeCards = new ArrayList<>(); //消耗牌
    @FieldTypeAnnotation(desc = "手牌")
    private List<FoxHandCard> handCards = new ArrayList<>(); //手牌
    @FieldTypeAnnotation(desc = "剩余手牌库")
    private List<FoxHandCard> remainHandCards = new ArrayList<>(); //剩余手牌库
    @FieldTypeAnnotation(desc = "弃牌库")
    private List<FoxHandCard> dropHandCards = new ArrayList<>(); //弃牌库
    @FieldTypeAnnotation(desc = "出牌次数")
    private int showCardTimes; //出牌次数
    @FieldTypeAnnotation(desc = "弃牌次数")
    private int dropCardTimes; //弃牌次数
    @FieldTypeAnnotation(desc = "出牌次数上限")
    private int showCardTimesMax; //出牌次数
    @FieldTypeAnnotation(desc = "弃牌次数上限")
    private int dropCardTimesMax; //弃牌次数
    @FieldTypeAnnotation(desc = "金币数量")
    private int gold; //金币数量
    @FieldTypeAnnotation(desc = "伤害量")
    private BigInteger damageAmount = BigInteger.ZERO; //伤害量
    @FieldTypeAnnotation(desc = "等待选择的牌")
    private List<FoxSaleCard> waitChooseCards = new ArrayList<>();
    @FieldTypeAnnotation(desc = "剩余选择数量")
    private int remainChooseTimes; //剩余选择数量
    @FieldTypeAnnotation(desc = "拥有的优惠券")
    private List<Integer> coupons = new ArrayList<>(); //拥有的优惠券
    @FieldTypeAnnotation(desc = "boss限制效果")
    private int bossLimitEffect; //boss限制效果
    @FieldTypeAnnotation(desc = "获得的跳过效果")
    private List<Integer> skipLabelHaves = new ArrayList<>(); //获得的跳过效果
    @FieldTypeAnnotation(desc = "最大卡牌id")
    private int maxCardId; //最大卡牌id,用来生成卡牌唯一id用
    @FieldTypeAnnotation(desc = "是否在商店")
    private boolean isShopping = false; //是否在商店
    @FieldTypeAnnotation(desc = "牌型组合统计")
    private Map<Integer, List<Integer>> comboInfoMap = new HashMap<>(); //牌型组合信息 key:牌型 value:等级,打出次数

    @FieldTypeAnnotation(desc = "累计使用消耗卡")
    private Map<Integer, Integer> consumeCardTimesMap = new HashMap<>();
    @FieldTypeAnnotation(desc = "累计计分增强效果")
    private Map<Integer, Integer> historyBuffTimesMap = new HashMap<>(); //累计计分增强效果 key:效果id value:次数
    @FieldTypeAnnotation(desc = "累计计分点数牌次数")
    private Map<Integer, Integer> showPointAmountMap = new HashMap<>(); //累计出牌次数 key:点数 value:次数
    @FieldTypeAnnotation(desc = "累计弃点数牌次数")
    private Map<Integer, Integer> dropPointAmountMap = new HashMap<>(); //累计弃牌次数 key:点数 value:次数
    @FieldTypeAnnotation(desc = "累计跳过次数")
    private int skipTimesAmount;
    @FieldTypeAnnotation(desc = "累计出牌次数")
    private int showTimesAmount;
    @FieldTypeAnnotation(desc = "累计弃牌次数")
    private int dropTimesAmount;
    @FieldTypeAnnotation(desc = "上次使用的消耗牌id=configId*100+cardType")
    private int lastUsedConsumeCardId;
    @FieldTypeAnnotation(desc = "本回合上次计分的牌型")
    private int roundLastShowCombo;
    @FieldTypeAnnotation(desc = "本回合失效的小丑牌唯一id")
    private Set<Integer> roundLimitEffectCard = new HashSet<>();
    @FieldTypeAnnotation(desc = "本回合打出过的牌型")
    private Set<Integer> roundShowCombos = new HashSet<>();
    @FieldTypeAnnotation(desc = "最大单次伤害")
    private BigInteger maxOnceDamage = BigInteger.ZERO;

    private UserFoxCardShop shop; //商店
    private Map<Integer, UserFoxCardMonster> monsterMap = new ConcurrentHashMap<>(); //怪物信息

    public UserFoxCardGameData(int activityId, long userId) {
        this.activityId = activityId;
        this.userId = userId;
        setInsertOption();
    }

    public UserFoxCardGameData() {
    }

    public int getStageId() {
        return stageId;
    }

    public void setStageId(int stageId) {
        this.stageId = stageId;
    }

    public int getRound() {
        return round;
    }

    public void setRound(int round) {
        this.round = round;
    }

    public int getEffectCardNumLimit() {
        return effectCardNumLimit;
    }

    public void setEffectCardNumLimit(int effectCardNumLimit) {
        this.effectCardNumLimit = effectCardNumLimit;
    }

    public int getConsumeCardNumLimit() {
        return consumeCardNumLimit;
    }

    public void setConsumeCardNumLimit(int consumeCardNumLimit) {
        this.consumeCardNumLimit = consumeCardNumLimit;
    }

    public int getHandCardNumLimit() {
        return handCardNumLimit;
    }

    public void setHandCardNumLimit(int handCardNumLimit) {
        this.handCardNumLimit = handCardNumLimit;
    }

    public List<FoxEffectCard> getEffectCards() {
        return effectCards;
    }

    public void setEffectCards(List<FoxEffectCard> effectCards) {
        this.effectCards = effectCards;
    }

    public List<FoxConsumeCard> getConsumeCards() {
        return consumeCards;
    }

    public void setConsumeCards(List<FoxConsumeCard> consumeCards) {
        this.consumeCards = consumeCards;
    }

    public List<FoxHandCard> getHandCards() {
        return handCards;
    }

    public void setHandCards(List<FoxHandCard> handCards) {
        this.handCards = handCards;
    }

    public List<FoxHandCard> getRemainHandCards() {
        return remainHandCards;
    }

    public void setRemainHandCards(List<FoxHandCard> remainHandCards) {
        this.remainHandCards = remainHandCards;
    }

    public List<FoxHandCard> getDropHandCards() {
        return dropHandCards;
    }

    public void setDropHandCards(List<FoxHandCard> dropHandCards) {
        this.dropHandCards = dropHandCards;
    }

    public int getShowCardTimes() {
        return showCardTimes;
    }

    public void setShowCardTimes(int showCardTimes) {
        this.showCardTimes = showCardTimes;
    }

    public int getDropCardTimes() {
        return dropCardTimes;
    }

    public void setDropCardTimes(int dropCardTimes) {
        this.dropCardTimes = dropCardTimes;
    }

    public int getShowCardTimesMax() {
        return showCardTimesMax;
    }

    public void setShowCardTimesMax(int showCardTimesMax) {
        this.showCardTimesMax = showCardTimesMax;
    }

    public int getDropCardTimesMax() {
        return dropCardTimesMax;
    }

    public void setDropCardTimesMax(int dropCardTimesMax) {
        this.dropCardTimesMax = dropCardTimesMax;
    }

    public int getGold() {
        return gold;
    }

    public void setGold(int gold) {
        this.gold = gold;
    }

    public BigInteger getDamageAmount() {
        return damageAmount;
    }

    public void setDamageAmount(BigInteger damageAmount) {
        this.damageAmount = damageAmount;
    }

    public UserFoxCardShop getShop() {
        return shop;
    }

    public void setShop(UserFoxCardShop shop) {
        this.shop = shop;
    }

    public List<FoxSaleCard> getWaitChooseCards() {
        return waitChooseCards;
    }

    public void setWaitChooseCards(List<FoxSaleCard> waitChooseCards) {
        this.waitChooseCards = waitChooseCards;
    }

    public int getRemainChooseTimes() {
        return remainChooseTimes;
    }

    public void setRemainChooseTimes(int remainChooseTimes) {
        this.remainChooseTimes = remainChooseTimes;
    }

    public Map<Integer, List<Integer>> getComboInfoMap() {
        return comboInfoMap;
    }

    public void setComboInfoMap(Map<Integer, List<Integer>> comboInfoMap) {
        this.comboInfoMap = comboInfoMap;
    }

    public List<Integer> getCoupons() {
        return coupons;
    }

    public void setCoupons(List<Integer> coupons) {
        this.coupons = coupons;
    }

    public int getBossLimitEffect() {
        return bossLimitEffect;
    }

    public void setBossLimitEffect(int bossLimitEffect) {
        this.bossLimitEffect = bossLimitEffect;
    }

    public List<Integer> getSkipLabelHaves() {
        return skipLabelHaves;
    }

    public void setSkipLabelHaves(List<Integer> skipLabelHaves) {
        this.skipLabelHaves = skipLabelHaves;
    }

    public boolean getIsShopping() {
        return isShopping;
    }

    public void setIsShopping(boolean shopping) {
        isShopping = shopping;
    }

    public int getMaxCardId() {
        return maxCardId;
    }

    public void setMaxCardId(int maxCardId) {
        this.maxCardId = maxCardId;
    }

    public int getActivityId() {
        return activityId;
    }

    public void setActivityId(int activityId) {
        this.activityId = activityId;
    }

    public long getUserId() {
        return userId;
    }

    public void setUserId(long userId) {
        this.userId = userId;
    }

    public UserFoxCardMonster getMonster(int round) {
        return monsterMap.get(round);
    }

    public void addMonsters(List<UserFoxCardMonster> monsters) {
        for (UserFoxCardMonster monster : monsters) {
            monsterMap.put(monster.getRound(), monster);
        }
    }

    public Map<Integer, UserFoxCardMonster> getMonsterMap() {
        return monsterMap;
    }

    public void setMonsterMap(Map<Integer, UserFoxCardMonster> monsterMap) {
        this.monsterMap = monsterMap;
    }

    public Map<Integer, Integer> getConsumeCardTimesMap() {
        return consumeCardTimesMap;
    }

    public void setConsumeCardTimesMap(Map<Integer, Integer> consumeCardTimesMap) {
        this.consumeCardTimesMap = consumeCardTimesMap;
    }

    public Map<Integer, Integer> getHistoryBuffTimesMap() {
        return historyBuffTimesMap;
    }

    public void setHistoryBuffTimesMap(Map<Integer, Integer> historyBuffTimesMap) {
        this.historyBuffTimesMap = historyBuffTimesMap;
    }

    public int generalCardUniqueId() {
        return ++maxCardId;
    }

    public Map<Integer, Integer> getShowPointAmountMap() {
        return showPointAmountMap;
    }

    public void setShowPointAmountMap(Map<Integer, Integer> showPointAmountMap) {
        this.showPointAmountMap = showPointAmountMap;
    }

    public Map<Integer, Integer> getDropPointAmountMap() {
        return dropPointAmountMap;
    }

    public void setDropPointAmountMap(Map<Integer, Integer> dropPointAmountMap) {
        this.dropPointAmountMap = dropPointAmountMap;
    }

    public int getSkipTimesAmount() {
        return skipTimesAmount;
    }

    public void setSkipTimesAmount(int skipTimesAmount) {
        this.skipTimesAmount = skipTimesAmount;
    }

    public boolean getInBattle() {
        return inBattle;
    }

    public void setInBattle(boolean inBattle) {
        this.inBattle = inBattle;
        setUpdateOption();
    }

    public int getShowTimesAmount() {
        return showTimesAmount;
    }

    public void setShowTimesAmount(int showTimesAmount) {
        this.showTimesAmount = showTimesAmount;
    }

    public int getDropTimesAmount() {
        return dropTimesAmount;
    }

    public void setDropTimesAmount(int dropTimesAmount) {
        this.dropTimesAmount = dropTimesAmount;
    }

    public int getLastUsedConsumeCardId() {
        return lastUsedConsumeCardId;
    }

    public void setLastUsedConsumeCardId(int lastUsedConsumeCardId) {
        this.lastUsedConsumeCardId = lastUsedConsumeCardId;
    }

    public int getRoundLastShowCombo() {
        return roundLastShowCombo;
    }

    public void setRoundLastShowCombo(int roundLastShowCombo) {
        this.roundLastShowCombo = roundLastShowCombo;
    }

    public Set<Integer> getRoundLimitEffectCard() {
        return roundLimitEffectCard;
    }

    public void setRoundLimitEffectCard(Set<Integer> roundLimitEffectCard) {
        this.roundLimitEffectCard = roundLimitEffectCard;
    }

    public Set<Integer> getRoundShowCombos() {
        return roundShowCombos;
    }

    public void setRoundShowCombos(Set<Integer> roundShowCombos) {
        this.roundShowCombos = roundShowCombos;
    }

    public BigInteger getMaxOnceDamage() {
        return maxOnceDamage;
    }

    public void setMaxOnceDamage(BigInteger maxOnceDamage) {
        this.maxOnceDamage = maxOnceDamage;
    }

    public void copy(UserFoxCardGameData gameData) {
        this.setStageId(gameData.getStageId());
        this.setRound(gameData.getRound());
        this.setInBattle(gameData.getInBattle());
        this.setEffectCardNumLimit(gameData.getEffectCardNumLimit());
        this.setConsumeCardNumLimit(gameData.getConsumeCardNumLimit());
        this.setHandCardNumLimit(gameData.getHandCardNumLimit());
        this.setEffectCards(gameData.getEffectCards());
        this.setConsumeCards(gameData.getConsumeCards());
        this.setHandCards(gameData.getHandCards());
        this.setRemainHandCards(gameData.getRemainHandCards());
        this.setDropHandCards(gameData.getDropHandCards());
        this.setShowCardTimes(gameData.getShowCardTimes());
        this.setDropCardTimes(gameData.getDropCardTimes());
        this.setShowCardTimesMax(gameData.getShowCardTimesMax());
        this.setDropCardTimesMax(gameData.getDropCardTimesMax());
        this.setGold(gameData.getGold());
        this.setDamageAmount(gameData.getDamageAmount());
        this.setWaitChooseCards(gameData.getWaitChooseCards());
        this.setRemainChooseTimes(gameData.getRemainChooseTimes());
        this.setCoupons(gameData.getCoupons());
        this.setBossLimitEffect(gameData.getBossLimitEffect());
        this.setSkipLabelHaves(gameData.getSkipLabelHaves());
        this.setMaxCardId(gameData.getMaxCardId());
        this.setIsShopping(gameData.getIsShopping());
        this.setComboInfoMap(gameData.getComboInfoMap());
        this.setConsumeCardTimesMap(gameData.getConsumeCardTimesMap());
        this.setHistoryBuffTimesMap(gameData.getHistoryBuffTimesMap());
        this.setShowPointAmountMap(gameData.getShowPointAmountMap());
        this.setDropPointAmountMap(gameData.getDropPointAmountMap());
        this.setSkipTimesAmount(gameData.getSkipTimesAmount());
        this.setShowTimesAmount(gameData.getShowTimesAmount());
        this.setDropTimesAmount(gameData.getDropTimesAmount());
        this.setLastUsedConsumeCardId(gameData.getLastUsedConsumeCardId());
        this.setRoundLastShowCombo(gameData.getRoundLastShowCombo());
        this.setRoundLimitEffectCard(gameData.getRoundLimitEffectCard());
        this.setRoundShowCombos(gameData.getRoundShowCombos());
        this.setMaxOnceDamage(gameData.getMaxOnceDamage());

        for (UserFoxCardMonster copyMonster : gameData.getMonsterMap().values()) {
            UserFoxCardMonster monster = this.getMonster(copyMonster.getRound());
            if (monster == null) {
                monster = new UserFoxCardMonster(activityId, userId, copyMonster.getRound());
                monsterMap.put(monster.getRound(), monster);
            }
            monster.setSkipEffect(copyMonster.getSkipEffect());
            monster.setBossLimitEffect(copyMonster.getBossLimitEffect());
            monster.setHp(copyMonster.getHp());
        }

        for (UserFoxCardMonster monster : monsterMap.values()) {
            if (!gameData.getMonsterMap().containsKey(monster.getRound())) {
                monster.resetValue();
            }
        }

        if (gameData.getShop() != null) {
            if (this.shop == null) {
                this.shop = new UserFoxCardShop(activityId, userId);
            }

            this.shop.copy(gameData.getShop());
        }
        setUpdateOption();
    }

    public UserFoxCardGameData clone() {
        UserFoxCardGameData gameData = new UserFoxCardGameData();
        gameData.setStageId(this.getStageId());
        gameData.setRound(this.getRound());
        gameData.setInBattle(this.getInBattle());
        gameData.setEffectCardNumLimit(this.getEffectCardNumLimit());
        gameData.setConsumeCardNumLimit(this.getConsumeCardNumLimit());
        gameData.setHandCardNumLimit(this.getHandCardNumLimit());
        for (FoxEffectCard effectCard : this.effectCards) {
            gameData.effectCards.add(effectCard.clone());
        }
        for (FoxConsumeCard consumeCard : this.consumeCards) {
            gameData.consumeCards.add(consumeCard.clone());
        }
        for (FoxHandCard handCard : this.handCards) {
            gameData.handCards.add(handCard.clone());
        }
        for (FoxHandCard handCard : this.remainHandCards) {
            gameData.remainHandCards.add(handCard.clone());
        }
        for (FoxHandCard handCard : this.dropHandCards) {
            gameData.dropHandCards.add(handCard.clone());
        }
        gameData.setShowCardTimes(this.getShowCardTimes());
        gameData.setDropCardTimes(this.getDropCardTimes());
        gameData.setShowCardTimesMax(this.getShowCardTimesMax());
        gameData.setDropCardTimesMax(this.getDropCardTimesMax());
        gameData.setGold(this.getGold());
        gameData.setDamageAmount(this.getDamageAmount());
        for (FoxSaleCard saleCard : this.waitChooseCards) {
            gameData.waitChooseCards.add(saleCard.clone());
        }
        gameData.setRemainChooseTimes(this.getRemainChooseTimes());
        gameData.setCoupons(this.getCoupons());
        gameData.setBossLimitEffect(this.getBossLimitEffect());
        gameData.setSkipLabelHaves(new ArrayList<>(this.getSkipLabelHaves()));
        gameData.setMaxCardId(this.getMaxCardId());
        gameData.setIsShopping(this.getIsShopping());
        gameData.setShop(this.getShop().clone());
        gameData.setComboInfoMap(new HashMap<>(this.getComboInfoMap()));
        for (UserFoxCardMonster monster : this.getMonsterMap().values()) {
            if (monster.getHp().compareTo(BigInteger.ZERO) == 0) {
                continue;
            }
            gameData.monsterMap.put(monster.getRound(), monster.clone());
        }
        gameData.setConsumeCardTimesMap(new HashMap<>(this.getConsumeCardTimesMap()));
        gameData.setHistoryBuffTimesMap(new HashMap<>(this.getHistoryBuffTimesMap()));
        gameData.setShowPointAmountMap(new HashMap<>(this.getShowPointAmountMap()));
        gameData.setDropPointAmountMap(new HashMap<>(this.getDropPointAmountMap()));
        gameData.setSkipTimesAmount(this.getSkipTimesAmount());
        gameData.setShowTimesAmount(this.getShowTimesAmount());
        gameData.setDropTimesAmount(this.getDropTimesAmount());
        gameData.setLastUsedConsumeCardId(this.getLastUsedConsumeCardId());
        gameData.setRoundLastShowCombo(this.getRoundLastShowCombo());
        gameData.setRoundLimitEffectCard(new HashSet<>(this.getRoundLimitEffectCard()));
        gameData.setRoundShowCombos(new HashSet<>(this.getRoundShowCombos()));
        gameData.setMaxOnceDamage(this.getMaxOnceDamage());
        return gameData;
    }

    public void removeLabel(int labelId) {
        for (int i = 0; i < skipLabelHaves.size(); i++) {
            if (skipLabelHaves.get(i) == labelId) {
                skipLabelHaves.remove(i);
                break;
            }
        }
    }
}
